/*
 * @Author: CodeHare
 * @Date: 2023-10-30 11:34:54
 * @LastEditors: yangni 920556271@qq.com
 * @LastEditTime: 2024-04-23 17:55:01
 * @Description: EMS参数设置之能量管理
 */
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:json_annotation/json_annotation.dart';
import 'package:yt_devops/components/gaps.dart';
import 'package:yt_devops/model/device_obj/data_type_model.dart';
import 'package:yt_devops/model/device_obj/output_data_model.dart';
import 'package:yt_devops/model/device_obj/services_model.dart';
import 'package:yt_devops/model/device_obj/spec/array_spec.dart';
import 'package:yt_devops/model/device_obj/spec/double_spec.dart';
import 'package:yt_devops/model/device_obj/spec/struct_spec.dart';
import 'package:yt_devops/pages/devices/device_tab/components/detail_grid_widget.dart';
import 'package:yt_devops/pages/devices/device_tab/device_detail/ems/self_develop_ems_romote_control/ems_params_setting/widgets/energy_management_model.dart';
import 'package:yt_devops/pages/devices/device_tab/model/device_item_model.dart';
import 'package:yt_devops/pages/site/site_setting/site_setting_base_info/widgets/item_widget.dart';
import 'package:yt_devops/resources/str_res_keys.dart';
import 'package:yt_devops/styles/styles.dart';
import 'package:yt_devops/utils/func_utils.dart';
import 'package:yt_devops/utils/socket/use_socket.dart';
import 'package:yt_devops/utils/socket/use_subscribe.dart';

import '../../../../../../../../components/log_utils.dart';
import '../../../../../../../../utils/enums.dart';
import 'energy_manage_set/energy_manage_set_view.dart';

class EnergyManagementWidget extends StatefulWidget {
  final String deviceId;

  const EnergyManagementWidget(this.deviceId, {super.key});

  @override
  State<EnergyManagementWidget> createState() => _EnergyManagementWidgetState();
}

class _EnergyManagementWidgetState extends State<EnergyManagementWidget> {
  /// 订阅 websocket
  UseSubsribe subsribe = UseSubsribe();

  /// 订阅在线状态 websocket
  UseSubsribe connectSubsribe = UseSubsribe();

  // 订阅的数据流
  StreamSubscription<Map<String, dynamic>>? streamSubscription;
  // 订阅的数据流
  StreamSubscription<Map<String, dynamic>>? connectStreamSubscription;

  /// 手动设置模型
  ServicesModel? manualModeSetting;

  ///备电模式设置模型
  ServicesModel? backupPowerModeSetting;

  /// 削峰填谷模式设置模型
  ServicesModel? peakShavingAndValleyFillingModeSetting;

  /// 尖峰平谷时段设置模型
  List<ServicesModel>? peakAndValleyTimeSettings;

  /// 当前设置模型
  List<ServicesModel>? curSettings;

  /// 设备数据
  Map<String, dynamic> _data = {};

  /// 递归获取物模型下每个指令集合
  List<OutputDataModel> outputList = [];

  ///尖峰平谷时段
  Map<int, List<ElectrovalenceModel>> _groupElectrovalence = {};

  /// 在线状态
  ConnectStatusType? connectStatus;

  String operateText = ResKey.deviceParameterSetting.tr;

  Color currentColor = Colour.offlineTextColor;

  @override
  void initState() {
    initModel();
    getOutputKeys();
    getData();
    getConnectStatus();
    super.initState();
  }

  @override
  void dispose() {
    streamSubscription?.cancel();
    connectStreamSubscription?.cancel();
    super.dispose();
  }

  getData() {
    var stream = subsribe.start([int.parse(widget.deviceId)], true).stream
      ..asBroadcastStream;
    streamSubscription = stream.listen((event) {
      initData(event);
    });
  }

  getConnectStatus() {
    var stream = connectSubsribe
        .start([int.parse(widget.deviceId)], true,
            type: MessageEventType.networkStatus)
        .stream
        .asBroadcastStream();
    connectStreamSubscription = stream.listen((data) {
      connectStatus = $enumDecodeNullable(
        $ConnectStatusTypeEnumMap,
        data['networkStatus'],
      );
      if (mounted) {
        setState(() {});
      }
    });
  }

  /// 初始化物模型
  initModel() {
    manualModeSetting =
        ServicesModel.fromJson(SelfDevelopEMSServicesModel.manualModeMap);
    backupPowerModeSetting =
        ServicesModel.fromJson(SelfDevelopEMSServicesModel.backupPowerModeMap);
    peakShavingAndValleyFillingModeSetting = ServicesModel.fromJson(
        SelfDevelopEMSServicesModel.peakShavingAndValleyFillingModeMap);

    peakAndValleyTimeSettings = [
      ServicesModel.fromJson(SelfDevelopEMSServicesModel.peakAndValleyPriceMap),
      ServicesModel.fromJson(SelfDevelopEMSServicesModel.peakAndValleyTimeMap)
    ];
  }

  /// 获取页面所有操作指令的key值
  getOutputKeys() {
    var settings = [
      manualModeSetting,
      backupPowerModeSetting,
      peakShavingAndValleyFillingModeSetting,
      ...peakAndValleyTimeSettings!
    ];
    outputList.clear();
    for (var element in settings) {
      List<OutputDataModel> outs = element?.outputData ?? [];
      for (var o in outs) {
        outputList.add(o);
      }
    }
  }

  List<OutputDataModel> flatOutputFromModel(DataTypeModel dataType,
      {String? id, OutputDataModel? outputData}) {
    List<OutputDataModel> keys = [];
    var type = dataType.type;
    if (type == DataTypeEnum.array) {
      ArraySpec spec = dataType.specs as ArraySpec;

      var ks = flatOutputFromModel(spec.item!);
      keys.addAll(ks);
    } else if (type == DataTypeEnum.struct) {
      StructSpec spec = dataType.specs as StructSpec;
      for (OutputDataModel o in spec.specs!) {
        var ks = flatOutputFromModel(o.dataType, outputData: o);
        keys.addAll(ks);
      }
    } else {
      keys.add(outputData!);
    }

    return keys;
  }

  /// 初始化数据
  initData(Map<String, dynamic>? dataSource) {
    _data = {};
    dataSource?.forEach((key, value) {
      var idx = outputList.indexWhere((element) => element.id == key);
      if (idx > -1) {
        var data = value;
        if (outputList[idx].dataType.type == DataTypeEnum.array) {
          data = jsonDecode(value);
        }
        _data.addAll({key: data});
      }
    });

    List<ElectrovalenceModel> list = _data['ElectrovalenceTimeFrame'] == null
        ? []
        : List.of(_data['ElectrovalenceTimeFrame'])
            .map((e) => ElectrovalenceModel.fromJson(e))
            .toList();
    _groupElectrovalence = groupByElectrovalenceType(list);
    if (mounted) {
      setState(() {});
    }
  }

  cancelSet() {
    curSettings = null;
    setState(() {});
  }

  Container _generateListHeader(String title, String operateText,
      {Function? onValueTap}) {
    return Container(
      height: 53,
      padding: EdgeInsets.fromLTRB(16.w, 0, 16.w, 0),
      alignment: Alignment.center,
      color: Colour.white,
      child: Row(
        mainAxisAlignment: MainAxisAlignment.spaceBetween,
        children: [
          Text(
            title,
            style: TextStyle(
              fontSize: 18.sp,
              fontWeight: FontWeight.w600,
              color: Colour.mainTextColor,
            ),
          ),
          GestureDetector(
            onTap: () {
              onValueTap?.call();
            },
            child: Text(
              operateText,
              style: TextStyle(
                fontSize: 14.sp,
                color: Colour.primaryColor,
                fontWeight: FontWeight.w400,
              ),
            ),
          ),
        ],
      ),
    );
  }

  toSet(int index) {
    if (connectStatus == ConnectStatusType.off) {
      return;
    }
    switch (index) {
      case 0:
        curSettings = [manualModeSetting!];
        break;
      case 1:
        curSettings = [peakShavingAndValleyFillingModeSetting!];
        break;
      case 2:
        curSettings = [backupPowerModeSetting!];
        break;
      case 3:
        curSettings = peakAndValleyTimeSettings;
        break;

      default:
        curSettings = null;
    }
    setState(() {});
  }

  confirmSet(bool success, {Map<String, dynamic>? data}) {
    if (success && data != null) {
      _data.addEntries(data.entries);
      curSettings = null;
      List maplist = _data['ElectrovalenceTimeFrame'] ?? [];
      List<ElectrovalenceModel> modellist = [];
      for (var i = 0; i < maplist.length; i++) {
        var electrovalenceType = maplist[i]['ElectrovalenceType'];
        if (electrovalenceType is String) {
          maplist[i]['ElectrovalenceType'] =
              int.parse(maplist[i]['ElectrovalenceType']);
        }
        var item = ElectrovalenceModel.fromJson(maplist[i]);
        modellist.add(item);
      }

      _groupElectrovalence = groupByElectrovalenceType(modellist);
      setState(() {});
    }
  }

  @override
  Widget build(BuildContext context) {
    currentColor = connectStatus == ConnectStatusType.off
        ? Colour.offlineTextColor
        : Colour.mainTextColor;

    if (curSettings != null) {
      return EnergyManageSetView(
        deviceId: widget.deviceId,
        servicesList: curSettings!,
        dataSource: _data,
        cancelCallBack: cancelSet,
        confirmCallBack: confirmSet,
      );
    } else {
      return SingleChildScrollView(
        physics: const AlwaysScrollableScrollPhysics(),
        child: Column(
          children: <Widget>[
            /// 手动模式设置
            Container(
              color: Colour.white,
              margin: const EdgeInsets.only(top: 10),
              padding: const EdgeInsets.only(bottom: 4),
              child: ListView.separated(
                physics: const NeverScrollableScrollPhysics(),
                shrinkWrap: true,
                padding: EdgeInsets.zero,
                itemBuilder: (context, index) {
                  if (index == 0) {
                    return _generateListHeader(
                        manualModeSetting?.name ?? '', operateText,
                        onValueTap: () => toSet(0));
                  } else {
                    var outputModel = manualModeSetting!.outputData[index - 1];
                    var spec = outputModel.dataType.specs as DoubleSpec;
                    return ItemWidget(
                      outputModel.name,
                      TextEditingController(
                          text: _data[outputModel.id]?.toString() ?? ''),
                      titleColor: Colour.lightTextColor,
                      unitString: spec.unit ?? '',
                      isShowDivider: false,
                      titleFont: 14.sp,
                      unitTextColor: currentColor,
                      inputTextColor: currentColor,
                    );
                  }
                },
                separatorBuilder: (BuildContext context, int index) => Divider(
                  color: Colour.dividerColor,
                  height: 1,
                  indent: 16.w,
                  endIndent: 16.w,
                ),
                itemCount: (manualModeSetting?.outputData.length ?? 0) + 1,
              ),
            ),

            /// 削峰填谷模式设置
            Container(
              color: Colour.white,
              margin: const EdgeInsets.only(top: 10),
              child: ListView.separated(
                physics: const NeverScrollableScrollPhysics(),
                padding: EdgeInsets.zero,
                shrinkWrap: true,
                itemBuilder: (context, index) {
                  final outputModel = index == 0
                      ? null
                      : peakShavingAndValleyFillingModeSetting
                          ?.outputData[index - 1];

                  if (index == 0) {
                    return _generateListHeader(
                        peakShavingAndValleyFillingModeSetting?.name ?? '',
                        operateText,
                        onValueTap: () => toSet(1));
                  } else if (index == 1 || index == 2) {
                    var spec = outputModel?.dataType.specs as DoubleSpec?;
                    return ItemWidget(
                      outputModel!.name,
                      TextEditingController(
                        text: _data[outputModel.id]?.toString() ?? '',
                      ),
                      titleColor: Colour.lightTextColor,
                      unitString: spec?.unit ?? '',
                      titleFont: 14.sp,
                      unitTextColor: currentColor,
                      inputTextColor: currentColor,
                    );
                  } else {
                    if (_data == null || _data.isEmpty) {
                      return const SizedBox();
                    }
                    ArraySpec spec = outputModel?.dataType.specs as ArraySpec;
                    StructSpec structpsecs = spec.item?.specs as StructSpec;
                    var list = _data[outputModel!.id] as List;

                    ;
                    Map enums = structpsecs.specs![1].dataType.specs as Map;

                    return ListView.separated(
                        physics: const NeverScrollableScrollPhysics(),
                        padding: EdgeInsets.zero,
                        shrinkWrap: true,
                        itemBuilder: (context, index) => Container(
                              padding: EdgeInsets.only(left: 16.w),
                              height: 50,
                              child: Row(
                                children: <Widget>[
                                  SizedBox(
                                    child: Text(
                                      '${ResKey.deviceTimePeriod.tr}${index + 1}：',
                                      style: TextStyle(
                                        fontSize: 14.sp,
                                        color: Colour.lightTextColor,
                                      ),
                                    ),
                                  ),
                                  SizedBox(
                                    width: 95.w,
                                    child: Text(
                                      list[index]['pcsRunningTimeFrame'],
                                      style: TextStyle(color: currentColor),
                                    ),
                                  ),
                                  Container(
                                    padding: EdgeInsets.only(left: 8.w),
                                    alignment: Alignment.center,
                                    child: Text(
                                      enums[list[index]['CorD'].toString()] ??
                                          ' ',
                                      style: TextStyle(color: currentColor),
                                    ),
                                  ),
                                  Expanded(
                                    child: SizedBox(
                                      width: 72.w,
                                      child: Text(
                                        '${'siteMonitor.executionPower'.tr}：',
                                        textAlign: TextAlign.right,
                                        style: const TextStyle(
                                          color: Colour.labelTextColor,
                                        ),
                                      ),
                                    ),
                                  ),
                                  ConstrainedBox(
                                    constraints: BoxConstraints(minWidth: 40.w),
                                    child: Text(
                                      list[index]['executionPower'].toString(),
                                      style: TextStyle(color: currentColor),
                                    ),
                                  ),
                                  Padding(
                                    padding: EdgeInsets.only(right: 16.w),
                                    child: Text(
                                      'kW',
                                      style: TextStyle(
                                        color: currentColor,
                                        fontSize: 14.sp,
                                      ),
                                    ),
                                  ),
                                ],
                              ),
                            ),
                        separatorBuilder: (context, index) => const Divider(
                              color: Colour.dividerColor,
                              height: 1,
                            ),
                        itemCount: list.length);
                  }
                },
                separatorBuilder: (BuildContext context, int index) => Divider(
                  color: Colour.dividerColor,
                  height: 1,
                  indent: index == 0 ? 0 : 16.w,
                  endIndent: index == 0 ? 0 : 16.w,
                ),
                itemCount: (peakShavingAndValleyFillingModeSetting
                            ?.outputData.length ??
                        0) +
                    1,
              ),
            ),

            /// 备电设置
            Container(
              color: Colour.white,
              margin: const EdgeInsets.only(top: 10),
              padding: const EdgeInsets.only(bottom: 10),
              child: ListView.separated(
                physics: const NeverScrollableScrollPhysics(),
                shrinkWrap: true,
                itemBuilder: (context, index) {
                  if (index == 0) {
                    return _generateListHeader(
                        backupPowerModeSetting?.name ?? '',
                        ResKey.parameterSets.tr,
                        onValueTap: () => toSet(2));
                  } else {
                    var outputModel =
                        backupPowerModeSetting!.outputData[index - 1];
                    var spec = outputModel.dataType.specs as DoubleSpec;
                    return ItemWidget(
                      outputModel.name,
                      TextEditingController(
                          text: _data[outputModel.id]?.toString() ?? ''),
                      titleColor: Colour.lightTextColor,
                      unitString: spec.unit ?? '',
                      isShowDivider: false,
                      titleFont: 14.sp,
                      unitTextColor: currentColor,
                      inputTextColor: currentColor,
                    );
                  }
                },
                separatorBuilder: (context, index) => const Divider(
                  color: Colour.dividerColor,
                  height: 1,
                ),
                itemCount: (backupPowerModeSetting?.outputData.length ?? 0) + 1,
              ),
            ),

            /// 尖峰平谷时段设置
            Container(
                color: Colour.white,
                margin: const EdgeInsets.only(top: 10),
                padding: const EdgeInsets.only(bottom: 10),
                child: ListView.separated(
                  physics: const NeverScrollableScrollPhysics(),
                  shrinkWrap: true,
                  itemBuilder: (context, index) {
                    if (index == 0) {
                      return _generateListHeader(
                          peakAndValleyTimeSettings![index].name,
                          ResKey.parameterSets.tr,
                          onValueTap: () => toSet(3));
                    } else if (index == 1) {
                      var outputs = peakAndValleyTimeSettings![0].outputData;
                      return Padding(
                        padding: EdgeInsets.only(left: 16.w),
                        child: DetailGridWidget(
                            title: ResKey.peakValleyElePrices.tr,
                            dataSource: _data,
                            isLightTtext: connectStatus == ConnectStatusType.off
                                ? true
                                : false,
                            items: outputs
                                .map((e) => DetailItemModel(
                                    label: e.name,
                                    field: e.id,
                                    format: (value) =>
                                        FuncUtils.getValueWithUnit(
                                            _data[e.id],
                                            (e.dataType.specs as DoubleSpec)
                                                    .unit ??
                                                '')))
                                .toList()),
                      );
                    } else {
                      var service = peakAndValleyTimeSettings![1];
                      var list = getElectrovalenceTimeFrameWidget(
                          _groupElectrovalence);
                      return ListView.separated(
                          padding: EdgeInsets.symmetric(horizontal: 16.w),
                          shrinkWrap: true,
                          physics: const NeverScrollableScrollPhysics(),
                          itemBuilder: (context, outputIndex) {
                            if (outputIndex == 0) {
                              return Padding(
                                padding:
                                    const EdgeInsets.symmetric(vertical: 16),
                                child: Text(ResKey.peakValleyPeriods.tr,
                                    style: TextStyles.f16.mediumStyle),
                              );
                            } else {
                              return list[outputIndex - 1];
                            }
                          },
                          separatorBuilder: (context, index) => const Divider(
                                height: 1,
                                color: Colour.dividerColor,
                              ),
                          itemCount: list.length + 1);
                    }
                  },
                  separatorBuilder: (context, index) => const Divider(
                    color: Colour.dividerColor,
                    height: 1,
                  ),
                  itemCount: (peakAndValleyTimeSettings?.length ?? 0) + 1,
                ))
          ],
        ),
      );
    }
  }

  /// 尖峰平谷设置时间段组件
  List<Widget> getElectrovalenceTimeFrameWidget(
      Map<int, List<ElectrovalenceModel>> electrovalenceMap) {
    OutputDataModel output = peakAndValleyTimeSettings![1].outputData[0];

    StructSpec structSpec =
        ((output.dataType.specs as ArraySpec).item!.specs) as StructSpec;

    Map enums = (structSpec.specs![1]).dataType.specs as Map;
    List<Widget> widgets = [];
    electrovalenceMap.forEach((key, value) {
      var w = Column(
        children: [
          Gaps.vGap16,
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                ResKey.deviceElectricityPriceType.tr,
                style: TextStyles.lf14,
              ),
              Text(
                '${enums[key.toString()]}${ResKey.deviceElectrovalence.tr}',
              ),
            ],
          ),
          Gaps.vGap8,
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(
                ResKey.siteSettingElectricityTimeStage.tr,
                style: TextStyles.lf14,
              ),
              SizedBox(
                width: 180.w,
                child: GridView.builder(
                  shrinkWrap: true,
                  physics: const NeverScrollableScrollPhysics(),
                  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: value.length > 1 ? 2 : 1,
                      childAspectRatio: 3.5),
                  itemBuilder: (context, index) => Text(
                    value[index].timeFrame,
                    textAlign: TextAlign.right,
                  ),
                  itemCount: value.length,
                ),
              )
            ],
          ),
        ],
      );
      widgets.add(w);
    });
    return widgets;
  }

  /// 获取 ElectrovalenceType 为分组的列表
  Map<int, List<ElectrovalenceModel>> groupByElectrovalenceType(
      List<ElectrovalenceModel> list) {
    Map<int, List<ElectrovalenceModel>> map = {};
    for (var m in list) {
      if (map.keys.contains(m.electrovalenceType)) {
        map[m.electrovalenceType]!.add(m);
      } else {
        map.putIfAbsent(m.electrovalenceType, () => [m]);
      }
    }
    return map;
  }
}
